﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;

namespace KP_CommonLibrary.KP_CommonControls.NumericInput
{
    public class NumericMaskLogic
{
    // Fields
    private static char[] allDigits = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
    private CultureInfo culture;
    private int maxDigitsAfterDecimalSeparator;
    private int maxDigitsBeforeDecimalSeparator;
    private int minDigitsAfterDecimalSeparator;
    private int minDigitsBeforeDecimalSeparator;

    // Methods
    public NumericMaskLogic(int maxDigitsBeforeDecimalSeparator, int minDigitsBeforeDecimalSeparator, int minDigitsAfterDecimalSeparator, int maxDigitsAfterDecimalSeparator, CultureInfo culture)
    {
        this.Init(maxDigitsBeforeDecimalSeparator, minDigitsBeforeDecimalSeparator, minDigitsAfterDecimalSeparator, maxDigitsAfterDecimalSeparator, culture);
    }

    private MaskLogicResult CreateResult(string resultCandidate, int cursorBase)
    {
        int index = resultCandidate.IndexOf('.');
        if (index < 0)
        {
            index = resultCandidate.Length;
            if (this.maxDigitsAfterDecimalSeparator > 0)
            {
                resultCandidate = resultCandidate + '.';
            }
        }
        while (((index > this.minDigitsBeforeDecimalSeparator) && (resultCandidate[0] == '0')) && (cursorBase > 0))
        {
            resultCandidate = resultCandidate.Substring(1);
            cursorBase--;
            index--;
        }
        if (index <= this.maxDigitsBeforeDecimalSeparator)
        {
            while (index < this.minDigitsBeforeDecimalSeparator)
            {
                index++;
                cursorBase++;
                resultCandidate = '0' + resultCandidate;
            }
            if ((resultCandidate.Length - index) > this.maxDigitsAfterDecimalSeparator)
            {
                resultCandidate = resultCandidate.Substring(0, (index + this.maxDigitsAfterDecimalSeparator) + 1);
                if (cursorBase > resultCandidate.Length)
                {
                    cursorBase = resultCandidate.Length;
                }
            }
            while (((resultCandidate.Length > cursorBase) && (this.minDigitsAfterDecimalSeparator < ((resultCandidate.Length - index) - 1))) && resultCandidate.EndsWith("0"))
            {
                resultCandidate = resultCandidate.Substring(0, resultCandidate.Length - 1);
            }
            while ((this.minDigitsAfterDecimalSeparator > 0) && ((resultCandidate.Length - index) <= this.minDigitsAfterDecimalSeparator))
            {
                resultCandidate = resultCandidate + '0';
            }
            return new MaskLogicResult(resultCandidate, cursorBase);
        }
        return null;
    }

    private static string Decrement(string number)
    {
        string str = string.Empty;
        for (int i = number.Length - 1; i >= 0; i--)
        {
            char ch = number[i];
            if (ch == '0')
            {
                str = '9' + str;
            }
            else
            {
                if ((ch >= '0') && (ch <= '9'))
                {
                    char ch2 = (char) (ch - '\x0001');
                    return (number.Substring(0, i) + ch2 + str);
                }
                str = ch + str;
            }
        }
        return null;
    }

    public static string Div100(string input)
    {
        if (input.IndexOf('.') < 0)
        {
            input = input + '.';
        }
        string str = string.Empty;
        foreach (char ch in input)
        {
            str = ch + str;
        }
        string str2 = Mul100(str);
        string str3 = string.Empty;
        foreach (char ch2 in str2)
        {
            str3 = ch2 + str3;
        }
        return str3;
    }

    private MaskLogicResult GetClimbModuloResult(string head, string tail)
    {
        string str = Increment(head);
        return this.CreateResult(str + tail, str.Length);
    }

    private MaskLogicResult GetDiveModuloResult(string head, string tail, bool canChSign, out bool chSign)
    {
        chSign = false;
        string str = Decrement(head);
        if (str == null)
        {
            if (!canChSign)
            {
                return this.CreateResult(string.Empty, 0);
            }
            chSign = true;
            string str2 = SubtractWithCarry(tail);
            if (str2 != null)
            {
                return this.CreateResult(head + str2, head.Length);
            }
            int length = head.LastIndexOf('0');
            if (length < 0)
            {
                str = '1' + head;
            }
            else
            {
                str = head.Substring(0, length) + '1' + head.Substring(length + 1);
            }
        }
        return this.CreateResult(str + tail, str.Length);
    }

    public MaskLogicResult GetEditResult(string head, string replaced, string tail, string inserted)
    {
        string str = RefineInput(inserted, this.culture);
        if ((str.Length == 0) && (inserted.Length != 0))
        {
            return null;
        }
        if ((str == ".") && (replaced.Length == 0))
        {
            string resultCandidate = head + tail;
            int index = resultCandidate.IndexOf('.');
            if (index >= 0)
            {
                return this.CreateResult(resultCandidate, index + 1);
            }
        }
        tail = this.PatchTailIfEmpty(tail);
        if ((str.IndexOf('.') >= 0) && (((this.maxDigitsAfterDecimalSeparator == 0) || (head.IndexOf('.') >= 0)) || (tail.IndexOf('.') >= 0)))
        {
            return null;
        }
        if (((replaced.IndexOf('.') >= 0) && (head.Length > 0)) && ((tail.Length > 0) && (str.IndexOf('.') < 0)))
        {
            return null;
        }
        return this.CreateResult(head + str + tail, head.Length + str.Length);
    }

    public MaskLogicResult GetSpinResult(string head, string tail, bool isModuloDecrement, bool canChSign, out bool chSign)
    {
        chSign = false;
        if (isModuloDecrement)
        {
            return this.GetDiveModuloResult(head, tail, canChSign, out chSign);
        }
        return this.GetClimbModuloResult(head, tail);
    }

    private static string Increment(string number)
    {
        string str = string.Empty;
        for (int i = number.Length - 1; i >= 0; i--)
        {
            char ch = number[i];
            if (ch == '9')
            {
                str = '0' + str;
            }
            else
            {
                if ((ch >= '0') && (ch <= '9'))
                {
                    char ch2 = (char) (ch + '\x0001');
                    return (number.Substring(0, i) + ch2 + str);
                }
                str = ch + str;
            }
        }
        return ('1' + str);
    }

    protected virtual void Init(int maxDigitsBeforeDecimalSeparator, int minDigitsBeforeDecimalSeparator, int minDigitsAfterDecimalSeparator, int maxDigitsAfterDecimalSeparator, CultureInfo culture)
    {
        this.maxDigitsBeforeDecimalSeparator = maxDigitsBeforeDecimalSeparator;
        this.maxDigitsAfterDecimalSeparator = maxDigitsAfterDecimalSeparator;
        this.minDigitsBeforeDecimalSeparator = minDigitsBeforeDecimalSeparator;
        this.minDigitsAfterDecimalSeparator = minDigitsAfterDecimalSeparator;
        this.culture = culture;
    }

    private static string Mul10(string input)
    {
        int index = input.IndexOf('.');
        if (index < 0)
        {
            index = input.Length;
            input = input + '.';
        }
        int num2 = input.IndexOfAny(allDigits, index);
        if (num2 < 0)
        {
            return (input.Substring(0, index) + '0' + input.Substring(index));
        }
        return string.Concat(new object[] { input.Substring(0, index), input.Substring(index + 1, num2 - index), '.', input.Substring(num2 + 1) });
    }

    public static string Mul100(string input)
    {
        return Mul10(Mul10(input));
    }

    private string PatchTailIfEmpty(string tail)
    {
        if (tail.Length <= 0)
        {
            return tail;
        }
        if (tail[0] != '.')
        {
            return tail;
        }
        for (int i = 1; i < tail.Length; i++)
        {
            if (tail[i] != '0')
            {
                return tail;
            }
        }
        return string.Empty;
    }

    private static string RefineInput(string dirtyInput, CultureInfo refineCulture)
    {
        if ((dirtyInput.Length == 1) && ((dirtyInput[0] == '.') || (dirtyInput[0] == ',')))
        {
            return ".";
        }
        if (refineCulture.NumberFormat.CurrencySymbol != string.Empty)
        {
            dirtyInput = dirtyInput.Replace(refineCulture.NumberFormat.CurrencySymbol, string.Empty);
        }
        string str = string.Empty;
        bool flag = false;
        foreach (char ch in dirtyInput)
        {
            if ((ch >= '0') && (ch <= '9'))
            {
                str = str + ch;
            }
            else if ((((ch == refineCulture.NumberFormat.NumberDecimalSeparator[0]) || (ch == refineCulture.NumberFormat.CurrencyDecimalSeparator[0])) || (((ch == '.') && ('.' != refineCulture.NumberFormat.NumberGroupSeparator[0])) && ('.' != refineCulture.NumberFormat.CurrencyGroupSeparator[0]))) && !flag)
            {
                str = str + '.';
                flag = true;
            }
        }
        return str;
    }

    private static string SubtractWithCarry(string number)
    {
        bool flag = false;
        string str = string.Empty;
        int num = number.Length - 1;
        while (true)
        {
            if (num < 0)
            {
                if (flag)
                {
                    return str;
                }
                return null;
            }
            char ch = number[num];
            if ((ch == '0') && !flag)
            {
                str = '0' + str;
            }
            else if (((ch >= '0') && (ch <= '9')) && !flag)
            {
                flag = true;
                char ch2 = (char) (('9' - ch) + 0x31);
                str = ch2 + str;
            }
            else if (((ch >= '0') && (ch <= '9')) && flag)
            {
                char ch3 = (char) (('9' - ch) + 0x30);
                str = ch3 + str;
            }
            else
            {
                str = ch + str;
            }
            num--;
        }
    }
}

    public class MaskLogicResult
    {
        // Fields
        private int cursorPosition;
        private string editText;

        // Methods
        public MaskLogicResult(string editText, int cursorPosition)
        {
            this.editText = editText;
            this.cursorPosition = cursorPosition;
        }

        // Properties
        public int CursorPosition
        {
            get
            {
                return this.cursorPosition;
            }
        }

        public string EditText
        {
            get
            {
                return this.editText;
            }
        }
    }




}
